﻿using System;
using System.Collections.Generic;
using System.Linq;
using Sustainalytics.Entities;
using System.Security.Claims;
using Sustainalytics.ScreeningTool.BL.Model;
using Sustainalytics.DataLayer;
using MongoDB.Driver;
using SpreadsheetGear;

namespace Sustainalytics.ScreeningTool.BL
{
    public class CUSIPISINClaimsCheckerBL
    {
        public static readonly string CLAIMTYPE_CUSIP = @"Tools/CUSIP";
        public static readonly string CLAIMTYPE_ISIN = @"Tools/ISIN";
        public static readonly string CLAIMVALUE = @"Allow.All";

        private static readonly string CUSIP_NAME = "CUSIP";
        private static readonly string ISIN_NAME = "ISIN";
        private static Guid _CUSIPTemplateCriteriaId = Guid.Empty;
        private static Guid _ISINTemplateCriteriaId = Guid.Empty;

        public bool HasISINClaim { get; set; } = false;
        public bool HasCUSIPClaim { get; set; } = false;

        public static Tuple<Guid, Guid> CollectIdsForTemplateCriteriaIsinAndCusip(string cnxString = null)
        {
            if (string.IsNullOrEmpty(cnxString))
                cnxString = System.Configuration.ConfigurationManager.ConnectionStrings["ClientPlatform"].ConnectionString;

            var idCusip = MongoDatabaseFactory.GetDatabase(cnxString)
                .GetCollection<TemplateCriteria>()
                .Find(x => x.Name == CUSIP_NAME)
                .Project(x => x.Id)
                .FirstOrDefault();

            var idIsin = MongoDatabaseFactory.GetDatabase(cnxString)
                .GetCollection<TemplateCriteria>()
                .Find(x => x.Name == ISIN_NAME)
                .Project(x => x.Id)
                .FirstOrDefault();

            return new Tuple<Guid, Guid>(idCusip, idIsin);
        }

        public void checkIsinCusipClaims(ClaimsPrincipal claimsPrincipal)
        {
            HasCUSIPClaim = claimsPrincipal.HasClaim(x => x.Type == CLAIMTYPE_CUSIP && x.Value == CLAIMVALUE);
            HasISINClaim = claimsPrincipal.HasClaim(x => x.Type == CLAIMTYPE_ISIN && x.Value == CLAIMVALUE);
        }
        
        
        public CUSIPISINClaimsCheckerBL()
        {// for production
            if (_CUSIPTemplateCriteriaId == Guid.Empty || _ISINTemplateCriteriaId == Guid.Empty)
            {
                var tuple = CollectIdsForTemplateCriteriaIsinAndCusip();
                _CUSIPTemplateCriteriaId = tuple.Item1;
                _ISINTemplateCriteriaId  = tuple.Item2;
            }
        }

        public CUSIPISINClaimsCheckerBL(Guid isinTCID, Guid cusipTCID)
        {// for unit tests
            _CUSIPTemplateCriteriaId = cusipTCID;
            _ISINTemplateCriteriaId = isinTCID;
        }
    }

    interface IInternalDataSource
    {
        int Count();
        int CountIsinUSCA();
    }
    class InternalDataSource : IInternalDataSource
    {
        readonly ScreeningReportData _input;
        readonly string _searchName;
        readonly string _usName;
        readonly string _caName;
        public InternalDataSource(ScreeningReportData input, string name, string USName, string CAName)
        {
            _usName = USName;
            _caName = CAName;
            _searchName = name;
            _input = input;
        }

        public int Count() { return _input.CompanyData.Count; }
        public int CountIsinUSCA()
        {
            return _input.CompanyData.Count(c =>
            {
                if (c.Contains(_searchName))
                {
                    string name = (c[_searchName]).AsString;
                    if (!string.IsNullOrEmpty(name))
                        return name.StartsWith(_usName, StringComparison.InvariantCultureIgnoreCase) 
                             || name.StartsWith(_caName, StringComparison.InvariantCultureIgnoreCase);
                }
                return false;
            });
        }
    }
    class InternalDataSourcePregen : IInternalDataSource
    {
        readonly IWorksheet _input;
        readonly string _usName;
        readonly string _caName;
        readonly List<FilterCriteria> _filterCriterias;
        readonly int _startPositionForCriterias;
        readonly Guid _isinTemplateCriteriaId;
        public InternalDataSourcePregen(
            IWorksheet input, 
            string name, 
            string USName, 
            string CAName, 
            List<FilterCriteria> filterCriterias, 
            Guid isinTemplateCriteriaId, 
            int startPositionForCriterias)
        {
            _input = input;
            _usName = USName;
            _caName = CAName;

            _filterCriterias = filterCriterias;
            _startPositionForCriterias = startPositionForCriterias;
            _isinTemplateCriteriaId = isinTemplateCriteriaId;
        }

        public int Count() { return _input.UsedRange.RowCount - 1 /*we assume there is a header line on top of data*/; }
        public int CountIsinUSCA()
        {
            var count = 0;
            var filterCriteria = _filterCriterias.FirstOrDefault(x => x.TemplateCriteriaId == _isinTemplateCriteriaId);
            if (filterCriteria != null)
            {
                var colum = _startPositionForCriterias + filterCriteria.Order;
                for (var r  = 1; r <= _input.UsedRange.RowCount -1 /*we assume there is a header line on top of data*/; r++)
                {
                    var cell = _input.Cells[r, colum];                    
                    var text = cell.Value as string;
                    if (!string.IsNullOrEmpty(text))
                    {
                        if (text.StartsWith(_usName, StringComparison.InvariantCultureIgnoreCase)
                           || text.StartsWith(_caName, StringComparison.InvariantCultureIgnoreCase))
                            count++;
                    }
                }             
            }
            return count;
        }
    }
}
